/**
*  \file can_int_rx.h
*
*  \brief Internal can receive function
*
*  \author dajin.li  <dajin.li@linde-china.cn>
*
*/

/*===============================================[ private includes  ]================================================*/
#include "can_int_rx.h"
#include "cancom.h"
#include "../assertor/assertor.h"
#include "../pal/pal_mem.h"
#include "../endian/endian_read.h"
#include "../nth/nth.h"
#include "../saturated/sinc.h"
#include "../sched/sched.h"
#include "../can/can.h"
#include "../endian/endian.h"
#include "../app/app.h"
#include "../crc16/crc16.h"
#include "../u2c/u2c_dataexchange.h"


/*===============================================[ private defines   ]================================================*/

/*V_INT_RX_PDO1 0x19A*/
#define m_int_pdo1_data                                     can_int_rx.signal.v_int_rx_pdo1.u8data
#define m_int_pdo1_steer_angle                              can_int_rx.signal.v_int_rx_pdo1.store.m_steer_angle
#define m_int_pdo1_park_break_in_d                          can_int_rx.signal.v_int_rx_pdo1.store.m_park_break_in_d
#define m_int_pdo1_neutral_position_in_d                    can_int_rx.signal.v_int_rx_pdo1.store.m_neutral_position_in_d
#define m_int_pdo1_reverse_in_d                             can_int_rx.signal.v_int_rx_pdo1.store.m_reverse_in_d
#define m_int_pdo1_forward_in_d                             can_int_rx.signal.v_int_rx_pdo1.store.m_forward_in_d
#define m_int_pdo1_key_switch_in_d                          can_int_rx.signal.v_int_rx_pdo1.store.m_key_switch_in_d
#define m_int_pdo1_msg_cnt_can                              can_int_rx.signal.v_int_rx_pdo1.store.m_int_pdo1_msg_cnt
#define m_int_pdo1_inv2_enable                              can_int_rx.signal.v_int_rx_pdo1.store.m_inv2_enable
#define m_int_pdo1_inv1_enable                              can_int_rx.signal.v_int_rx_pdo1.store.m_inv1_enable
#define m_int_pdo1_seat_switch_in_d                         can_int_rx.signal.v_int_rx_pdo1.store.m_seat_switch_in_d
#define m_int_pdo1_seat_switch_nc_in_d                      can_int_rx.signal.v_int_rx_pdo1.store.m_seat_switch_nc_in_d
#define m_int_pdo1_msg_checksum_can                         can_int_rx.signal.v_int_rx_pdo1.store.m_int_pdo1_msg_checksum

/*V_INT_RX_PDO2 0x29A*/
#define m_int_pdo2_data                                     can_int_rx.signal.v_int_rx_pdo2.u8data
#define m_int_pdo2_accelerator                              can_int_rx.signal.v_int_rx_pdo2.store.m_accelerator
#define m_int_pdo2_dc_link_in_a                             can_int_rx.signal.v_int_rx_pdo2.store.m_dc_link_in_a
#define m_int_pdo2_msg_cnt_can                              can_int_rx.signal.v_int_rx_pdo2.store.m_int_pdo2_msg_cnt
#define m_int_pdo2_power_board_variant                      can_int_rx.signal.v_int_rx_pdo2.store.m_power_board_variant
#define m_int_pdo2_msg_checksum_can                         can_int_rx.signal.v_int_rx_pdo2.store.m_int_pdo2_msg_checksum

/*V_INT_RX_PDO3 0x39A*/
#define m_int_pdo3_data                                     can_int_rx.signal.v_int_rx_pdo3.u8data
#define m_int_pdo3_5v_current_sensor_in_a                   can_int_rx.signal.v_int_rx_pdo3.store.m_5v_current_sensor_in_a
#define m_int_pdo3_msg_cnt_can                              can_int_rx.signal.v_int_rx_pdo3.store.m_int_pdo3_msg_cnt
#define m_int_pdo3_msg_checksum_can                         can_int_rx.signal.v_int_rx_pdo3.store.m_int_pdo3_msg_checksum

/*V_INT_RX_PDO4 0x49A*/
#define m_int_pdo4_data                                     can_int_rx.signal.v_int_rx_pdo4.u8data
#define m_int_pdo4_137v_supply_in_a                         can_int_rx.signal.v_int_rx_pdo4.store.m_137v_supply_in_a
#define m_int_pdo4_msg_cnt_can                              can_int_rx.signal.v_int_rx_pdo4.store.m_int_pdo4_msg_cnt
#define m_int_pdo4_msg_checksum_can                         can_int_rx.signal.v_int_rx_pdo4.store.m_int_pdo4_msg_checksum

/*===============================================[ private datatypes ]================================================*/
struct can_int_rx_signal
{
    union
    {
        U8  u8data[8];
        struct
        {
            U8  m_reserve0;                            /*Byte0     0  :7*/
            U8  m_reserve1;                            /*Byte1     8  :15*/
            S16 m_steer_angle;                         /*Byte2&3   16 :31 0.1 degree*/
            U8  m_park_break_in_d:1;                   /*Byte4     32 :32*/
            U8  m_neutral_position_in_d:1;             /*Byte4     33 :33*/
            U8  m_reverse_in_d:1;                      /*Byte4     34 :34*/
            U8  m_forward_in_d:1;                      /*Byte4     35 :35*/
            U8  m_reserve2:3;                          /*Byte4     36 :38*/
            U8  m_key_switch_in_d:1;                   /*Byte5     39 :39*/
            U8  m_int_pdo1_msg_cnt:4;                  /*Byte5     40 :43*/
            U8  m_inv2_enable:1;                       /*Byte5     44 :44*/
            U8  m_inv1_enable:1;                       /*Byte5     45 :45*/
            U8  m_seat_switch_in_d:1;                  /*Byte5     46 :46*/
            U8  m_seat_switch_nc_in_d:1;               /*Byte5     47 :47*/
            U16 m_int_pdo1_msg_checksum;               /*Byte6&7   48 :63*/
        }store;
    }v_int_rx_pdo1;


    union
    {
        U8  u8data[8];
        struct
        {
            S16 m_accelerator;                         /*Byte0&1   0  :15 0.1 %*/
            S16 m_dc_link_in_a;                        /*Byte2&3   16 :31 0.01 V*/
            U8  reserve0;                              /*Byte4     32 :39*/
            U8  m_int_pdo2_msg_cnt:4;                  /*Byte5     40 :43*/
            U8  m_power_board_variant:4;               /*Byte5     44 :47*/
            U16 m_int_pdo2_msg_checksum;               /*Byte6&7   48 :63*/
        }store;
    }v_int_rx_pdo2;


    union
    {
        U8  u8data[8];
        struct
        {
            S16 m_5v_current_sensor_in_a;              /*Byte0&1   0  :15 mv*/
            U16 reserve0;                              /*Byte2&3   16 :31*/
            U8  reserve1;                              /*Byte4     32 :39*/
            U8  m_int_pdo3_msg_cnt:4;                  /*Byte5     40 :43*/
            U8  reserve2:4;                            /*Byte5     44 :47*/
            U16 m_int_pdo3_msg_checksum;               /*Byte6&7   48 :63*/
        }store;
    }v_int_rx_pdo3;

    union
    {
        U8  u8data[8];
        struct
        {
            S16 m_137v_supply_in_a;                    /*Byte0&1   0  :15 v, 0.01*/
            U16 reserve0;                              /*Byte2&3   16 :31*/
            U8  reserve1;                              /*Byte4     32 :39*/
            U8  m_int_pdo4_msg_cnt:4;                  /*Byte5     40 :43*/
            U8  reserve2:4;                            /*Byte5     44 :47*/
            U16 m_int_pdo4_msg_checksum;               /*Byte6&7   48 :63*/
        }store;
    }v_int_rx_pdo4;
};
/** Private variables */
struct can_int_rx_private
{
   struct tasklet task_10ms;
   struct tasklet task_1ms;
   struct tasklet task_idle;
   struct can_int_rx_signal signal;
};

/*===============================================[ private variables ]================================================*/
static struct can_int_rx_private can_int_rx;

/*===============================================[ private functions ]================================================*/
static void can_int_rx_10ms_service (struct tasklet *task);
static void can_int_rx_1ms_service (struct tasklet *task);
static void can_int_rx_idle_service (struct tasklet *task);
static void can_int_rx_process_pdo1(struct canmsg* msg, void *data );
static void can_int_rx_process_pdo2(struct canmsg* msg, void *data );
static void can_int_rx_process_pdo3(struct canmsg* msg, void *data );
static void can_int_rx_process_pdo4(struct canmsg* msg, void *data );

/*================================================[ inline functions ]================================================*/

/*================================================[ public functions ]================================================*/
RC can_int_rx_initialize( void )
{
   pal_memzero( &can_int_rx, sizeof can_int_rx );

   tasklet_assign( sched_get_slice_10ms(), &can_int_rx.task_10ms,  can_int_rx_10ms_service, NIL );
   tasklet_assign( sched_get_slice_1ms(),  &can_int_rx.task_1ms,   can_int_rx_1ms_service,  NIL );
   tasklet_assign( sched_get_slice_idle(), &can_int_rx.task_idle,  can_int_rx_idle_service, NIL );

   can_install_rx_callback( can_channel_int, V_INT_RX_PDO1, can_int_rx_process_pdo1,  (void*)can_int_rx.signal.v_int_rx_pdo1.u8data );
   can_install_rx_callback( can_channel_int, V_INT_RX_PDO2, can_int_rx_process_pdo2,  (void*)can_int_rx.signal.v_int_rx_pdo2.u8data );
   can_install_rx_callback( can_channel_int, V_INT_RX_PDO3, can_int_rx_process_pdo3,  (void*)can_int_rx.signal.v_int_rx_pdo3.u8data );
   can_install_rx_callback( can_channel_int, V_INT_RX_PDO4, can_int_rx_process_pdo4,  (void*)can_int_rx.signal.v_int_rx_pdo4.u8data );

   return RC_SUCCESS;
}

/*===============================================[ private functions ]================================================*/

/** 10ms Service function
*
*   \param task Pointer to calling tasklet.
*
*/
static void can_int_rx_10ms_service (struct tasklet *task)
{
    UNREFERENCED( task );

}

/** 1ms Service function
*
*   \param task Pointer to calling tasklet.
*
*/
static void can_int_rx_1ms_service (struct tasklet *task)
{
    UNREFERENCED( task );
}

/** Idle Service function
*
*   \param task Pointer to calling tasklet.
*
*/
static void can_int_rx_idle_service (struct tasklet *task)
{
    UNREFERENCED( task );
}

static void can_int_rx_process_pdo1(struct canmsg* msg, void *data )
{
    U16 can_id = V_INT_RX_PDO1;
    U16 checksum = 0;
    pal_memcpy(data, canmsg_data_ptr(msg), canmsg_get_dlc(msg));

    checksum = crc16(0xffff,&can_id,2);

    if(crc16(checksum, m_int_pdo1_data, 6) == m_int_pdo1_msg_checksum_can)
    {
        u2c_data_input.motor_steer_angle_m       = m_int_pdo1_steer_angle;
        u2c_data_input.motor_park_brake_in_m     = m_int_pdo1_park_break_in_d;
        u2c_data_input.motor_neutral_position_m  = m_int_pdo1_neutral_position_in_d;
        u2c_data_input.motor_reverse_in_m        = m_int_pdo1_reverse_in_d;
        u2c_data_input.motor_forward_in_m        = m_int_pdo1_forward_in_d;
        u2c_data_input.motor_inv2_enable_m       = m_int_pdo1_inv2_enable;
        u2c_data_input.motor_inv1_enable_m       = m_int_pdo1_inv1_enable;
        u2c_data_input.motor_seat_switch_in_m    = m_int_pdo1_seat_switch_in_d;
        u2c_data_input.motor_seat_switch_nc_in_m = m_int_pdo1_seat_switch_nc_in_d;
        u2c_data_input.motor_keyswitch_in_m      = m_int_pdo1_key_switch_in_d;
		
    }
    else
    {
        pal_memzero(m_int_pdo1_data, 6);
    }
}
static void can_int_rx_process_pdo2(struct canmsg* msg, void *data )
{
    U16 can_id = V_INT_RX_PDO2;
    U16 checksum = 0;
    pal_memcpy(data, canmsg_data_ptr(msg), canmsg_get_dlc(msg));
    checksum = crc16(0xffff,&can_id,2);
    if(crc16(checksum, m_int_pdo2_data, 6) == m_int_pdo2_msg_checksum_can)
    {
        u2c_data_input.motor_accelerator_m          = m_int_pdo2_accelerator;
        u2c_data_input.motor_dc_link_in_m           = m_int_pdo2_dc_link_in_a;
        u2c_data_input.motor_power_board_variant_m  = m_int_pdo2_power_board_variant;
    }
    else
    {
        pal_memzero(m_int_pdo2_data, 6);
    }
}
static void can_int_rx_process_pdo3(struct canmsg* msg, void *data )
{
    U16 can_id = V_INT_RX_PDO3;
    U16 checksum = 0;
    pal_memcpy(data, canmsg_data_ptr(msg), canmsg_get_dlc(msg));
    checksum = crc16(0xffff,&can_id,2);
    if(crc16(checksum, m_int_pdo3_data, 6) == m_int_pdo3_msg_checksum_can)
    {
        u2c_data_input.motor_current_sensors_vol_m  = m_int_pdo3_5v_current_sensor_in_a;
    }
    else
    {
        pal_memzero(m_int_pdo3_data, 6);
    }
}
static void can_int_rx_process_pdo4(struct canmsg* msg, void *data )
{
    U16 can_id = V_INT_RX_PDO4;
    U16 checksum = 0;
    pal_memcpy(data, canmsg_data_ptr(msg), canmsg_get_dlc(msg));
    checksum = crc16(0xffff,&can_id,2);
    if(crc16(checksum, m_int_pdo4_data, 6) == m_int_pdo4_msg_checksum_can)
    {
        u2c_data_input.motor_power_supply_m  = m_int_pdo4_137v_supply_in_a;
    }
    else
    {
        pal_memzero(m_int_pdo4_data, 6);
    }
}

/***********************************************************************************************************************
*                             Copyright 2018 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
